package com.longsichao.lscframe.net;

import com.longsichao.lscframe.app.LSCApplication;
import com.longsichao.lscframe.tools.LSCLog;

import java.io.File;
import java.io.IOException;
import java.util.Set;

import okhttp3.Cache;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * @author SONG GUANYULONGSICHAO (leo.song[at]outlook[dot]com)
 */
public final class HttpConnection {
    private static final long HTTP_RESPONSE_DISK_CACHE_MAX_SIZE = 10 * 1024 * 1024;// 10MB
    private static OkHttpClient httpClient = null;

    public static OkHttpClient getHttpClient() {
        if (httpClient == null) {
            httpClient = init();
        }
        return httpClient;
    }

    private static OkHttpClient init() {
        final File baseDir = LSCApplication.applicationContext.getCacheDir();
        if (baseDir != null) {
            final File cacheDir = new File(baseDir, "HttpResponseCache");
            httpClient = new OkHttpClient.Builder().cache(new Cache(cacheDir, HTTP_RESPONSE_DISK_CACHE_MAX_SIZE)).build();
        }
        return httpClient;
    }

    public HttpConnection() {
        if (httpClient == null) {
            httpClient = init();
        }
    }

    public String get(Api api) throws IOException {
        Request.Builder builder = new Request.Builder();
        builder.url(api.getUrl());

        if (api.getHeader() != null) {
            String name = api.getHeader().getName();
            String value = api.getHeader().getValue();
            if (name != null && !name.isEmpty() && value != null && !value.isEmpty()) {
                builder.removeHeader(name);
                builder.addHeader(name, value);
            } else {
                LSCLog.v("Set request header, but name or value is empty.");
            }
        }

        Request request = builder.build();

        LSCLog.v("Execute " + request.toString());

        Response response = httpClient.newCall(request).execute();

        if (!response.isSuccessful()) {
            throw new IOException("Unexpected code " + response);
        }

        // Callback response header
        if (api.getHeader() != null && api.getHeader().getListener() != null) {
            Set<String> names = response.headers().names();
            for (String name : names) {
                api.getHeader().getListener().onResponseHeader(name, response.headers().get(name));
            }
        }

        LSCLog.v("Return " + response.toString());

        return response.body().string();
    }

    public String post(Api api) throws IOException {
        // Create request body
        RequestBody requestBody;
        if (api.getPostFiles().isEmpty()) {
            requestBody = RequestBody.create(api.getPostString().getMediaType(), api.getPostString().getValue());
        } else {

            MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);

            for (Api.FileSet fileSet : api.getPostFiles()) {
                builder.addFormDataPart(fileSet.getName(), fileSet.getFile().getName(), RequestBody.create(fileSet.getMediaType(), fileSet.getFile()));
            }

            requestBody = builder.build();
        }

        // Create request header
        Request.Builder builder = new Request.Builder().url(api.getUrl()).post(requestBody);
        if (api.getHeader() != null) {
            String name = api.getHeader().getName();
            String value = api.getHeader().getValue();
            if (name != null && !name.isEmpty() && value != null && !value.isEmpty()) {
                builder.removeHeader(name);
                builder.addHeader(name, value);
            } else {
                LSCLog.v("Set request header, but name or value is empty.");
            }
        }
        Request request = builder.build();

        LSCLog.v("Execute " + request.toString());

        // Execute request
        Response response = httpClient.newCall(request).execute();
        if (!response.isSuccessful()) {
            throw new IOException("Unexpected code " + response);
        }

        // Callback response header
        if (api.getHeader() != null && api.getHeader().getListener() != null) {
            Set<String> names = response.headers().names();
            for (String name : names) {
                api.getHeader().getListener().onResponseHeader(name, response.headers().get(name));
            }
        }

        LSCLog.v("Return " + response.toString());

        // return response body
        return response.body().string();
    }
}
